﻿using FTBS.Models.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.Entity.Infrastructure;
using FTBS.Models.Entities.Concert;
using System.Transactions;

namespace FTBS.Models.DAO
{
    public class TheaterDAO
    {
        private FilmTicketBookingSystemEntities _entities = new FilmTicketBookingSystemEntities();
        //private SettingTheaterDAO _settingTheaterDao = new SettingTheaterDAO();

        /// <summary>
        /// Get All Information Of Theater
        /// </summary>
        /// <returns>List of Theater</returns>
        /// <author>VuongVT</author>
        public List<Theater> GetAllTheaterInfo()
        {
            try
            {
                List<Theater> listTheater = new List<Theater>();
                var resultQuery = from theater in _entities.Theaters
                                  where theater.IsDeleted == false
                                  select theater;
                foreach (var theater in resultQuery)
                {
                    listTheater.Add(theater);
                }
                return listTheater;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Get All Information Of Theater to create price ticket
        /// </summary>
        /// <returns>List of Theater</returns>
        /// <author>HungPH</author>
        public List<Theater> GetAllTheaterInfoToCreatePriceTicket()
        {
            try
            {
                List<Theater> listTheater = new List<Theater>();
                var resultQuery = from theater in _entities.Theaters
                                  where theater.IsDeleted == false && (_entities.PriceTickets.Count(
                    pt => pt.IsDeleted == false && pt.TheaterId == theater.TheaterId)) == 0
                                  select theater;
                foreach (var theater in resultQuery)
                {
                    listTheater.Add(theater);
                }
                return listTheater;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Get All Information Of Theater By UserName of Supplier
        /// </summary>
        /// <returns>List of theaters</returns>
        /// <author>HungPH</author>
        public List<Theater> GetAllTheatersByUsernameOfSupplier(string username)
        {
            try
            {
                List<Theater> listTheater = new List<Theater>();
                var resultQuery = from theater in _entities.Theaters
                                  where theater.IsDeleted == false && theater.UserName == username
                                  select theater;
                foreach (var theater in resultQuery)
                {
                    listTheater.Add(theater);
                }
                return listTheater;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Get all theaters have film in Schedule
        /// </summary>
        /// <returns>List of Theater</returns>
        public List<Theater> GetAllTheatersInSchedule()
        {
            try
            {
                List<Theater> listTheater = new List<Theater>();
                var listResult = _entities.Schedules.Where(s => s.IsDeleted == false)
                                                    .GroupBy(s => s.TheaterId)
                                                    .Select(r => new
                                                    {
                                                        TheaterId = r.Key
                                                    })
                                                    .Join(_entities.Theaters, s => s.TheaterId, t => t.TheaterId, (s, t) => new { s, t })
                                                    .Select(r => new
                                                    {
                                                        Theater = r.t
                                                    });

                foreach (var item in listResult)
                {
                    listTheater.Add(item.Theater);
                }
                return listTheater;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Get Theater by Id
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns></returns>
        public Theater GetTheaterById(int theaterId)
        {
            var resultQuery = (from theater in _entities.Theaters
                               where theater.TheaterId == theaterId
                                     && theater.IsDeleted == false
                               select theater).FirstOrDefault();
            return resultQuery;
        }

        /// <summary>
        /// Check exist TheaterName
        /// </summary>
        /// <param name="theater"></param>
        /// <returns>true: Exist TheaterName -- false: Not Exist TheaterName</returns>
        public bool IsExistTheater(Theater theater)
        {
            List<Theater> resultQuery = (from th in _entities.Theaters
                                         where th.TheaterName == theater.TheaterName
                                            && th.IsDeleted == false
                                         select th).ToList();
            if (resultQuery.Count() >= 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Check Exist Theater when Update a theater
        /// </summary>
        /// <param name="theater"></param>
        /// <returns>true: Exist TheaterName -- false: Not Exist TheaterName</returns>
        /// <author>VuongVT</author>
        public bool IsExistTheaterUpdate(Theater theater)
        {
            try
            {
                bool resultQuery = _entities.Theaters.Any(th => th.TheaterId != theater.TheaterId
                                                          && th.TheaterName == theater.TheaterName
                                                          && th.IsDeleted == false);
                return resultQuery;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Create a new Theater
        /// </summary>
        /// <param name="theater"></param>
        /// <returns>1: success -- 0: fail</returns>
        public int CreateTheater(Theater theater)
        {
            try
            {
                _entities.Theaters.Add(theater);
                int result = _entities.SaveChanges();
                if (result == 1)
                {
                    return theater.TheaterId;
                }
                else
                {
                    return 0;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Edit a Theater
        /// </summary>
        /// <param name="theater"></param>
        /// <returns>1: Success --- 0: Fail</returns>
        public int EditTheater(Theater theater)
        {
            try
            {
                var startingIssue = _entities.Theaters.Find(theater.TheaterId);
                _entities.Detach(startingIssue);
                _entities.Entry(theater).State = EntityState.Modified;
                return _entities.SaveChanges();
            }
            catch (Exception)
            {
                return 0;
            }
        }



        /// <summary>
        /// get number of Schedule of theater
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns>number of schedule of theater</returns>
        /// <author>hungph</author>
        public int GetNumberOfScheduleOfTheater(int theaterId)
        {
            var count =
                _entities.Schedules.Count(schedule => schedule.TheaterId == theaterId && schedule.IsDeleted == false);
            return count;
        }

        /// <summary>
        /// get number of showTime of theater
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns>number of showTime of theater</returns>
        /// <author>hungph</author>
        public int GetNumberOfShowTimeOfTheater(int theaterId)
        {
            var count =
                _entities.ShowTimes.Count(showTime => showTime.TheaterId == theaterId && showTime.IsDeleted == false);
            return count;
        }

        /// <summary>
        /// get number of room of theater
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns>number of room of theater</returns>
        /// <author>hungph</author>
        public int GetNumberOfRoomOfTheater(int theaterId)
        {
            var count =
                _entities.Rooms.Count(room => room.TheaterId == theaterId && room.IsDeleted == false);
            return count;
        }

        /// <summary>
        /// get number of room of theater
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns>number of setting theater</returns>
        /// <author>hungph</author>
        public int GetNumberOfSettingTheater(int theaterId)
        {
            var count = _entities.Theaters.Count(setting => setting.TheaterId == theaterId);
            return count;
        }

        /// <summary>
        /// get number of price ticket of theater
        /// </summary>
        /// <param name="theaterId"></param>
        /// <returns>number of price ticket of theater</returns>
        /// <author>hungph</author>
        public int GetNumberOfPriceTicketOfTheater(int theaterId)
        {
            var count =
                _entities.PriceTickets.Count(priceTicket => priceTicket.TheaterId == theaterId && priceTicket.IsDeleted == false);
            return count;
        }

        /// <summary>
        /// Get theaters of a supplier
        /// </summary>
        /// <returns></returns>      
        /// <author>DuyHDV</author>
        public List<Theater> GetTheatersBySupplierName(string name)
        {
            List<Theater> listTheater = new List<Theater>();
            try
            {
                var results = (
                    from theater in _entities.Theaters
                    where theater.User.FullName == name &&
                          theater.User.IsActive == true &&
                          theater.User.IsDeleted == false &&
                          theater.IsDeleted == false
                    select theater);
                listTheater = results.ToList();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return listTheater;
        }

        /// <summary>
        /// Add new theater and theater's setting
        /// </summary>
        /// <param name="theaterAndSettingEnt"></param>
        /// <author>VuongVT</author>
        public int AddNewTheaterAndSetting(SettingTheaterConcertEntity theaterAndSettingEnt)
        {
            try
            {
                var isExistTheater = _entities.Theaters.Any(theater => theater.TheaterName == theaterAndSettingEnt.TheaterName
                                                         && theater.IsDeleted == false);
                Theater theaterEntity = new Theater();
                theaterEntity.TheaterId = theaterAndSettingEnt.TheaterId;
                theaterEntity.TheaterName = theaterAndSettingEnt.TheaterName;
                theaterEntity.Address = theaterAndSettingEnt.Address;
                theaterEntity.PhoneNumber = theaterAndSettingEnt.PhoneNumber;
                theaterEntity.UserName = theaterAndSettingEnt.UserName;
                theaterEntity.Latitude = theaterAndSettingEnt.Latitude;
                theaterEntity.Longitude = theaterAndSettingEnt.Longitude;
                theaterEntity.ImageURL = theaterAndSettingEnt.ImageURL;
                theaterEntity.MaxChairInRow = theaterAndSettingEnt.MaxChairInRow;
                theaterEntity.MaxColumnInRoom = theaterAndSettingEnt.MaxColumnInRoom;
                theaterEntity.MaxBookingTicket = theaterAndSettingEnt.MaxBookingTicket;
                theaterEntity.DeadlineCreateTicket = theaterAndSettingEnt.DeadlineCreateTicket;
                theaterEntity.PointWithMoney = theaterAndSettingEnt.PointWithMoney;
                theaterEntity.DeadlineForBooking = theaterAndSettingEnt.DeadlineForBooking;
                theaterEntity.TimeForBooking = theaterAndSettingEnt.TimeForBooking;
                theaterEntity.IsDeleted = theaterAndSettingEnt.IsDeleted;
                _entities.Theaters.Add(theaterEntity);
                int resultAddTheater = _entities.SaveChanges();
                return resultAddTheater;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Delete Theater
        /// Delete all room of theater
        /// Delete all chair of room
        /// Delete all schedule of Theater
        /// </summary>
        /// <param name="theater"></param>
        /// <returns></returns>
        public int DeleteTheater(Theater theater)
        {
            try
            {
                using (TransactionScope trans = new TransactionScope())
                {
                    try
                    {
                        //Delete theater
                        theater.IsDeleted = true;
                        _entities.Entry(theater).State = EntityState.Modified;
                        var resultDeleteTheater = _entities.SaveChanges();

                        //Delete Room of theater
                        var selectRoom = from room in _entities.Rooms
                                         where room.TheaterId == theater.TheaterId
                                               && room.IsDeleted == false
                                         select room;
                        foreach (var room in selectRoom)
                        {
                            room.IsDeleted = true;
                            _entities.Entry(room).State = EntityState.Modified;

                            //Delete Chairs of room
                            var selectChair = from chair in _entities.Chairs
                                              where chair.RoomId == room.RoomId
                                                    && chair.IsDeleted == false
                                              select chair;
                            foreach (var chair in selectChair)
                            {
                                chair.IsDeleted = true;
                                _entities.Entry(chair).State = EntityState.Modified;
                            }
                        }
                        var resultDeleteRoom = _entities.SaveChanges();

                        //Delete Schedule of Theater
                        var selectSchedule = from schedule in _entities.Schedules
                                             where schedule.TheaterId == theater.TheaterId
                                                   && schedule.IsDeleted == false
                                             select schedule;
                        foreach (var schedule in selectSchedule)
                        {
                            schedule.IsDeleted = true;
                            _entities.Entry(schedule).State = EntityState.Modified;
                        }

                        var resultDeleteSchedule = _entities.SaveChanges();
                        trans.Complete();
                        return resultDeleteSchedule;
                    }
                    catch (Exception)
                    {
                        trans.Dispose();
                        return 0;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        /// Check the TheaterId is used in Theater and doesn't have Booked ticket or not
        /// This function is used for user Click to Edit in List Theater
        /// </summary>
        /// <param name="showTimeId"></param>
        /// <returns>True: Is Exist ---- False: Not Exist</returns>
        /// <author>VuongVT</author>
        public bool IsTheaterUsedInScheduleAndBooked(int theaterId)
        {
            try
            {
                bool isUsedScheduleAndBooked = false;
                var selectSchedule = from schedule in _entities.Schedules
                                     where schedule.TheaterId == theaterId
                                           && schedule.IsDeleted == false
                                           && schedule.IsCreateTicket == true
                                     select schedule;
                var countSchedule = selectSchedule.Count();

                //Loop is list of schedules, if have any schedule use this theater, break loop
                foreach (var schedule in selectSchedule)
                {
                    var isBookedTicket = _entities.Tickets.Any(ticket => ticket.ScheduleId == schedule.ScheduleId
                                                                     && ticket.IsDeleted == false
                                                                     && ticket.Status == true);
                    if (isBookedTicket)
                    {
                        isUsedScheduleAndBooked = true;
                        break;
                    }
                }

                ////Get schedule have theaterId = theaterId
                //var scheduleId = (from schedule in _entities.Schedules
                //                  where schedule.TheaterId == theaterId
                //                        && schedule.IsDeleted == false
                //                        && schedule.IsCreateTicket == true
                //                  select schedule.ScheduleId).FirstOrDefault();

                //if (scheduleId != 0)
                //{
                //    var isBookedTicket = _entities.Tickets.Any(ticket => ticket.ScheduleId == scheduleId
                //                                                     && ticket.IsDeleted == false
                //                                                     && ticket.Status == true);
                //    if (isBookedTicket)
                //    {
                //        isUsedScheduleAndBooked = true;
                //    }
                //}
                return isUsedScheduleAndBooked;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Check the TheaterId is used in Schedule or not
        /// This function is used for user Click to Delete in List Theater
        /// </summary>
        /// <param name="showTimeId"></param>
        /// <returns>True: Is Exist ---- False: Not Exist</returns>
        /// <author>VuongVT</author>
        public bool IsTheaterUsedForSchedule(int theaterId)
        {
            try
            {
                var isUsedForSchedule = _entities.Schedules.Any(schedule => schedule.TheaterId == theaterId
                                                                            && schedule.IsDeleted == false);
                return isUsedForSchedule;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
